using System;
using System.Collections;
using System.Collections.Generic;
using PluginFramework.Client;

namespace PluginFramework.Plugins
{
	/// <summary>
	/// Creates and manages plugins of generic type.
	/// Every plugin will be created only once (singleton).
	/// Plugins should not store session/request data!
	/// They should act as ActionFilters of Asp.Net MVC
	/// </summary>
	/// <typeparam name="T">Inheritor of IPluginPart</typeparam>
	public class WebContextPluginsManager<T> :IDisposable, IEnumerable<T> where T : IPluginPart
	{
		private Dictionary<string, T> _list = new Dictionary<string, T>();
		private PluginsStateManager _stateManager;

		public WebContextPluginsManager(PluginsStateManager stateManager)
		{
			_stateManager = stateManager;
			_stateManager.OnDisablePlugins += OnDisable;
		}

		/// <summary>
		/// Gets list of instantiated plugins
		/// </summary>
		protected IDictionary<string, T> List
		{
			get { return _list; }
		}

		/// <summary>
		/// Gets plugins config
		/// </summary>
		public PluginsStateManager StateManager
		{
			get { return _stateManager; }
		}

		/// <summary>
		/// Create an instance of plugin with specified id
		/// </summary>
		/// <param name="id">plugin id</param>		
		/// <returns></returns>
		public T CreateInstance(string id)
		{
			if (List.ContainsKey(id)) return List[id];
			var t = _stateManager.CreateInstance<T>(id);
			List.Add(id, t);
			return t;
		}

		/// <summary>
		/// Invoked when plugins are disabled.
		/// Override to do maintenance for disabled plugins.
		/// Must be called after override.
		/// </summary>
		/// <param name="ids"></param>
		public virtual void OnDisable(IEnumerable<string> ids)
		{
			foreach(var id in ids) Remove(id);
		}

		/// <summary>
		/// Removes a plugin instance for list.
		/// </summary>
		/// <param name="id"></param>
		public virtual void Remove(string id)
		{
			if (List.ContainsKey(id)) List.Remove(id);
		}

		public IEnumerator<T> GetEnumerator()
		{
			return List.Values.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		/// <summary>
		/// Cleanup
		/// </summary>
		public virtual void Dispose()
		{
			if (_stateManager!=null) _stateManager.OnDisablePlugins -= OnDisable;
		}
	}
}